package com.qf.service.impl;

import com.qf.pojo.Order;
import com.qf.service.OrderService;
import com.qf.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    /*
        远程注入
        @Reference作用：
            ① 将这个对象生成代理对象（ReferenceBean-代理对象），添加到spring容器中
            ② 代理对象做了什么？
                1、从注册中心获取远程服务对象的信息（服务器协议、ip、端口、服务名称及其方法...），将其缓存在本地
                2、监听远程服务对象的信息变化
     */
//    @Reference(timeout = 4000)

    /*
        当消费方在向提供方发起远程访问时
            提供方一旦出现超时，后续业务是不会停止，而是继续向下执行完整个业务代码
            消费方一定出现超时，默认情况下会重试两次，所以会导致提供方的业务执行3次

            如果提供方的业务是幂等的业务，那么没问题；如果提供方的业务是一个非幂等的业务，最终就会导致数据错误。

            幂等操作：多次执行的结果是一样的，称之为米等操作。 1*1  1+1

                增：非幂等
                删：幂等
                改：
                    update xx set 列=值 where id=1;  --设置： 幂等
                    update xx set 列=列+值 where id=1;  --计算： 非幂等
                查：幂等

             结论：
                对于幂等业务，为了保证用户可以正常获取到数据结果，可以重试
                对于非幂等业务，不允许重试的
     */
//    @Reference(retries = 0)

    /*
        版本号测试
     */
//    @Reference(version = "1.0")

    /*
        负载均衡
            提供方有多台机器，消费在向提供方发起访问时，会通过某种策略找到其中一台机器发起访问，这种查找一台机器的策略就称之为负载均衡策略
            A-20   B-50

            Random: 加权随机
            ***RoundRobin: 加权轮询
            LeastActive:当前机器正在处理的请求数越小，后期越优先将请求打到这台机器 （能者多劳）
            ShortestResponse:根据服务器的响应时间评估，响应时间越短，后期越优先将请求打到这台机器
            ConsistentHash:根据参数进行hash运算，参数不变hash值也不变，请求到的机器都是同一台

            配置负载均衡策略时，所有字母都小写
     */
//    @Reference(loadbalance = "roundrobin")
//    @Reference(loadbalance = "consistenthash",parameters = "{name,zs}")

    /*
        集群容错：
            当集群环境下，通过负载均衡选择的那台服务器发生rpc异常，对待这种异常的策略称之为集群容错

            ***Failover：出错了，会重试其他机器  -- 幂等
            ***Failfast：出错了，直接提示错误，不再重试 -- 非幂等
            Failsafe：出错了不提示，悄摸得把错误吃掉
            Failback：出错了，一直重试那台出错的机器，值到机器恢复
            Forking：请求并发打到所有服务器，只要有一个成功，就返回成功
            Broadcast：串行调用每一台服务器，只要有一个失败，就返回失败
            Available：
            Mergeable：

     */
    @Reference(loadbalance = "roundrobin",cluster = "failfast",
            stub = "com.qf.stub.OrderServiceStub",
            mock = "com.qf.mock.OrderServiceMock"
    )
    private OrderService orderService;

    @Override
    public List<Order> findById(Integer uid) throws InterruptedException {
        System.out.println("通过远程调用查询用户订单");
        return orderService.findByUid(uid);
    }
}
